'''1.8.10 ctypes'''

from ctypes import windll, cdll, \
    c_int, c_wchar_p, c_ushort, c_long, c_double, \
    c_char_p, \
    create_string_buffer, sizeof


def loading_dynamic_link_ibraries():
    '''载入动态连接库'''
    # Windows
    print(windll.kernel32)
    print(cdll.msvcrt)
    # Linux
    # print(cdll.LoadLibrary('libc.so.6'))


def accessing_functions_from_loaded_dlls():
    '''操作导入的动态链接库中的函数'''
    print(cdll.msvcrt.printf)
    print(windll.kernel32.GetModuleHandleA)
    # AttributeError: function 'MyOwnFunction' not found
    # print(windll.kernel32.MyOwnFunction)
    # print(getattr(cdll.msvcrt, '??2@YAPAXI@Z'))
    # print(cdll.kernel32[0])


def calling_functions():
    '''调用函数'''
    print(cdll.msvcrt.time(None))
    print(hex(windll.kernel32.GetModuleHandleA(None)))
    print(cdll.kernel32.GetModuleHandleA(None))
    print(windll.msvcrt.printf(b'spam'))
    # OSError: exception: access violation reading 0x00000020
    # print(windll.kernel32.GetModuleHandleA(32))


def fundamental_data_types():
    '''基础数据类型'''
    print(c_int())
    print(c_wchar_p('Hello, World'))
    print(c_ushort(-3))
    i = c_int(42)
    print(i)
    c_long(42)
    print(i.value)
    s = 'Hello World'
    c_s = c_wchar_p(s)
    print(c_s)
    print(c_s.value)
    c_s.value = 'Hi, there'
    print(c_s)
    print(c_s.value)
    print(s)
    p = create_string_buffer(3)
    print(sizeof(p), repr(p.raw))
    p = create_string_buffer(b'Hello', 10)
    print(sizeof(p), repr(p.raw))
    p.value = b'Hi'
    print(sizeof(p), repr(p.raw))


def calling_functions_continued():
    '''调用函数，继续'''
    printf = cdll.msvcrt.printf
    printf(b'Hello, %s\n', b'World!')
    printf(b'Hello, %S\n', 'World!')
    printf(b'%d bottles of beer\n', 42)
    # printf(b'%f bottles of beer\n', 42.5)
    '''
    正如前面所提到过的，除了整数、字符串以及字节串之外，
    所有的 Python 类型都必须使用它们对应的 ctypes 类型包装，
    才能够被正确地转换为所需的C语言类型。
    '''
    printf(b'An int %d, a double %f\n', 1234, c_double(3.14))


def calling_varadic_functions():
    '''调用变长参数函数'''
    cdll.msvcrt.printf.argtypes = [c_char_p]


def calling_functions_with_your_own_custom_data_types():
    '''使用自定义的数据类型调用函数'''
    class Bottles:
        def __init__(self, number):
            self._as_parameter_ = number
    bottles = Bottles(42)
    cdll.msvcrt.printf(b'%d bottles of beer\n', bottles)


def return_types():
    '''返回类型'''
    strchr = cdll.msvcrt.strchr
    print(strchr(b'abcdef', ord('d')))
    strchr.restype = c_char_p    # c_char_p 是一个指向字符串的指针
    print(strchr(b'abcdef', ord('d')))
    print(strchr(b'abcdef', ord('x')))
